// src/core/ReferencePool.ts
/**
 * 引用接口，所有可池化的对象都需要实现此接口
 */
export interface IReference {
    /**
     * 清理引用对象，重置状态
     */
    clear(): void;
}

/**
 * 引用池类，提供对象池功能以减少垃圾回收压力
 */
export class ReferencePool {
    private static _pools: Map<new () => IReference, ReferencePoolItem> = new Map();


    
    /**
     * 获取引用池中的对象
     * @param classConstructor 对象的构造函数。
     * @returns 从池中获取的对象实例
     */

    public static acquire<T extends IReference>(classConstructor: new () => T): T {
        const pool = this.getPool(classConstructor);
        return pool.acquire() as T;
    }

    /**
     * 将对象归还到引用池
     * @param reference 要归还的对象
     */
    public static release(reference: IReference): void {
        const constructor = reference.constructor as new () => IReference;
        const pool = this.getPool(constructor);
        pool.release(reference);
    }

    /**
     * 向引用池中预添加指定数量的对象
     * @param classConstructor 对象的构造函数
     * @param count 预添加的数量
     */
    public static add<T extends IReference>(classConstructor: new () => T, count: number): void {
        const pool = this.getPool(classConstructor);
        pool.add(count);
    }

    /**
     * 获取引用池的统计信息
     * @param classConstructor 对象的构造函数
     * @returns 包含使用中和可用对象数量的信息
     */
    public static getInfo(classConstructor: new () => IReference): { using: number, available: number } | null {
        if (this._pools.has(classConstructor)) {
            const pool = this._pools.get(classConstructor)!;
            return {
                using: pool.usingCount,
                available: pool.availableCount
            };
        }
        return null;
    }

    /**
     * 清理指定类型的引用池
     * @param classConstructor 对象的构造函数
     */
    public static clear<T extends IReference>(classConstructor: new () => T): void {
        if (this._pools.has(classConstructor)) {
            const pool = this._pools.get(classConstructor)!;
            pool.clear();
            this._pools.delete(classConstructor);
        }
    }

    /**
     * 清理所有引用池
     */
    public static clearAll(): void {
        for (const pool of this._pools.values()) {
            pool.clear();
        }
        this._pools.clear();
    }

    /**
     * 获取或创建指定类型的引用池
     * @param classConstructor 对象的构造函数
     * @returns 对应的引用池实例
     */
    private static getPool<T extends IReference>(classConstructor: new () => T): ReferencePoolItem {
        if (!this._pools.has(classConstructor)) {
            const pool = new ReferencePoolItem(classConstructor);
            this._pools.set(classConstructor, pool);
            return pool;
        }
        return this._pools.get(classConstructor)!;
    }
}

/**
 * 引用池项，管理特定类型的对象池
 */
class ReferencePoolItem {
    private _classConstructor: new () => IReference;
    private _availableReferences: IReference[] = [];
    private _usingReferences: Set<IReference> = new Set();

    constructor(classConstructor: new () => IReference) {
        this._classConstructor = classConstructor;
    }

    /**
     * 从池中获取一个对象
     * @returns 对象实例
     */
    public acquire(): IReference {
        let reference: IReference;
        if (this._availableReferences.length > 0) {
            reference = this._availableReferences.pop()!;
        } else {
            reference = new this._classConstructor();
        }
        this._usingReferences.add(reference);
        return reference;
    }

    /**
     * 将对象归还到池中
     * @param reference 要归还的对象
     */
    public release(reference: IReference): void {
        if (!this._usingReferences.has(reference)) {
            return;
        }

        reference.clear();
        this._usingReferences.delete(reference);
        this._availableReferences.push(reference);
    }

    /**
     * 向池中添加指定数量的对象
     * @param count 添加的数量
     */
    public add(count: number): void {
        if (count <= 0) return;

        for (let i = 0; i < count; i++) {
            this._availableReferences.push(new this._classConstructor());
        }
    }

    /**
     * 清理池中所有对象
     */
    public clear(): void {
        this._availableReferences.length = 0;
        this._usingReferences.clear();
    }

    /**
     * 获取当前可用对象数量
     */
    public get availableCount(): number {
        return this._availableReferences.length;
    }

    /**
     * 获取当前使用中对象数量
     */
    public get usingCount(): number {
        return this._usingReferences.size;
    }
}